﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Comdiv.QWeb.Diagnostics;
using Comdiv.QWeb.Utils;

namespace Comdiv.QWeb.ViewEngine {
	public class QViewDescriptor : IQViewDescriptor, IRegistryBound {
		private readonly Stack<IQView> _views = new Stack<IQView>();
		protected IQViewCompiler compiler;
		private QWebServiceRegistry registry;
		public bool NeedRecompile { get; set; }
		public DateTime LastCompilation { get; set; }


		public Type Type { get; set; }

		#region IQViewDescriptor Members

		public string Name { get; set; }

		public QViewStats Stats { get; set; }

		public void ReleaseView(IQView view) {
			if (view.GetType() == Type) {
				_views.Push(view);
			}
		}


		public QViewSourceDescriptor Source { get; protected set; }

		public void Recompile() {
			NeedRecompile = true;
			if (GetNeedRecompile()) {
				Type = null;
			}
		}


		public IQView GetView() {
			lock (this) {
				if (null != Stats) Stats.Activations++;
				if (null == Type) {
					_views.Clear();
					var sw = Stopwatch.StartNew();
					Compile();
					sw.Stop();
					if (null != Stats) Stats.Compilations++;
					if (null != Stats) Stats.TotalCompileTime += sw.Elapsed;
				}
				if (0 != _views.Count) {
					return _views.Pop();
				}
				if (null != Stats) Stats.Creations++;
				if (null != compiler) {
					((IRegistryBound) compiler).Registry.Statistics.QViewEngineStatistics.Creations++;
				}
				return Type.create<IQView>();
			}
		}

		#endregion

		#region IRegistryBound Members

		public QWebServiceRegistry Registry {
			get { return registry; }
		}

		public void SetRegistry(QWebServiceRegistry registry) {
			this.registry = registry;
			compiler = registry.QViewCompiler;
			Source = new QViewSourceDescriptor(Name, registry.FileNameResolver);
			Source.Reset();
		}

		#endregion

		public virtual bool GetNeedRecompile() {
			if (!NeedRecompile) return false;
			if (Source.Sources.Length > 0) {
				if (Source.NeedRecompile || Source.SourceVersion > LastCompilation) {
					return true;
				}
			}
			return false;
		}

		protected virtual void Compile() {
			Type = compiler.Compile(this);
			NeedRecompile = false;
		}
	}
}